﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml;

namespace POC.Configuration
{
    public static class ConfigKeyConstant
    {
        public const string Host = "domain";
        public const string UseLocalAccount = "useLocalAccount";
        public const string Async = "async";
        public const string DevelopmentAzureAccount = "devAccount";
        public const string IsHttps = "isHttps";
        public const string UseSystemProxy = "useSystemProxy";
        public const string AzureAccount = "account";
        public const string StorageKey = "accessKey";
        public const string SecondaryStorageKey = "accessKey2";
        public const string ConfigFile = "configFile";
        public const string NodeName = "nodeName";
        public const string ReaderType = "readerType";
        public const string BaseUri = "root";
    }
    public static class ConfigValueConstant
    {
        public const string Host = "localhost";
        public const string AzureStorageBlobUriString = "blob.core.windows.net";
        public const string AzureStorageQueueUriString = "queue.core.windows.net";
        public const string AzureStorageTableUriString = "table.core.windows.net";
        public const string LocalHostStorageBlobUriString = "127.0.0.1:10000";
        public const string LocalHostStorageQueueUriString = "127.0.0.1:10001";
        public const string LocalHostStorageTableUriString = "127.0.0.1:10002";
    }

    public interface IConfigReader
    {
        string ReadNode(string key, string query);
        IDictionary<string, string> List(string query = "");
        string SetNode(string key, string val, string query);
    }

    public class AppConfigReader : IConfigReader
    {
        public string ReadNode(string key, string query)
        {
            return ConfigurationManager.AppSettings[key];
        }
        public IDictionary<string, string> List(string query)
        {
            return new Dictionary<string, string>();
        }
        public string SetNode(string key, string val, string query)
        {
            throw new NotImplementedException();
        }
    }
    public class SessionConfigReader : IConfigReader
    {
        public string ReadNode(string key, string query)
        {
            throw new NotImplementedException();
        }
        public IDictionary<string, string> List(string query)
        {
            throw new NotImplementedException();
        }


        public string SetNode(string key, string val, string query)
        {
            throw new NotImplementedException();
        }
    }

    public class AzureTableConfigReader : IConfigReader
    {
        public string ReadNode(string key, string query)
        {
            throw new NotImplementedException();
        }
        public IDictionary<string, string> List(string query)
        {
            throw new NotImplementedException();
        }


        public string SetNode(string key, string val, string query)
        {
            throw new NotImplementedException();
        }
    }
    public class FileConfigReader : IConfigReader
    {
        string _filePath = "";
        string _nodeName = "/configuration/appSettings";
        protected IDictionary<string, string> keyValues = new Dictionary<string, string>();
        protected List<Exception> errors = new List<Exception>();
        bool loaded = false;
        public string ConfigFile
        {
            get
            {
                return _filePath;
            }
            set
            {
                _filePath = value;
            }
        }
        public FileConfigReader(string filePath, string treePath = null)
        {
            _filePath = filePath;
            _nodeName = (treePath == null) ? _nodeName : treePath;
        }
        public string ReadNode(string key, string query)
        {
            if (!loaded)
            {
                keyValues = Load(ConfigFile);
                loaded = true;
            }
            if (keyValues == null)
            {
                string message = "The initial config file is not correct, either the path is wrong or file content is not in proper format.";
                message += errors.Any() ? "Possible reason : " + errors[0].Message : string.Empty;
                throw new ArgumentException(message);
            }
            var node = keyValues.ContainsKey(key) ? keyValues[key] : string.Empty;
            return node;
        }

        protected virtual IDictionary<string, string> Load(string filePath)
        {
            IDictionary<string, string> items = new Dictionary<string, string>();
            try
            {
                XmlDocument xdoc = new XmlDocument();
                xdoc.Load(filePath);
                XmlNode xnodes = xdoc.SelectSingleNode(_nodeName);
                if (xnodes.ChildNodes.Count > 0)
                {
                    foreach (XmlNode xnn in xnodes.ChildNodes)
                    {
                        if (xnn is XmlElement)
                        {
                            string key = xnn.Attributes["key"].Value;
                            string value = xnn.Attributes["value"].Value;
                            items[key] = value;
                        }
                    }
                }
            }
            catch (Exception parseEx)
            {
                errors.Add(parseEx);
            }
            return items;
        }
        public IDictionary<string, string> List(string query)
        {
            //Alread read
            IDictionary<string, string> nodes = keyValues;
            if (!string.IsNullOrEmpty(query))
            {
                _nodeName = query;
                nodes = Load(_filePath);
            }
            return nodes;
        }
        public IDictionary<string, string> Reload()
        {
            keyValues = Load(_filePath);
            loaded = true;
            return keyValues;
        }
        public string SetNode(string key, string val, string query = "")
        {
            if (keyValues == null)
            {
                keyValues = new Dictionary<string, string>();
            }
            if (keyValues.ContainsKey(key))
            {
                keyValues[key] = val;
            }
            else
            {
                keyValues.Add(key, val);
            }
            return val;
        }
    }
    public class TextFileConfigReader : FileConfigReader
    {
        string rootFilePath = string.Empty;
        public TextFileConfigReader()
            : this("")
        {
            string fileName = System.Reflection.Assembly.GetEntryAssembly().Location;
            ConfigFile = fileName.Replace("exe", "txt");
        }
        public TextFileConfigReader(string filePath)
            : base(filePath)
        {

        }
        protected override IDictionary<string, string> Load(string filePath)
        {
            IDictionary<string, string> items = new Dictionary<string, string>();
            try
            {
                string[] lines = File.ReadAllLines(filePath);
                foreach (var line in lines)
                {
                    string[] keyvalue = line.Trim().Split('=');
                    if (keyvalue.Length == 2 && keyvalue[0][0] != '#')
                    {
                        string key = keyvalue[0].Trim().Replace("[equal]", "=");
                        string val = keyvalue[1].Trim().Replace("[equal]", "=");
                        items.Add(key, val);
                    }
                }
            }
            catch (Exception parseEx)
            {
                errors.Add(parseEx);
            }
            return items;
        }
    }
  
}
